﻿using System.Collections.Generic;

using System.Net.DnsToolkit.Packet;
using System.Net.DnsToolkit.Serializer.Stream.Compression;
using System.Net.DnsToolkit.Serializer.Stream.Extension;

namespace System.Net.DnsToolkit.Serializer.Stream {
    public class MessageWriter : IMessageWriter<System.IO.Stream> {

        private readonly IHeaderWriter<System.IO.Stream> _headerWriter;
        private readonly IQuestionWriter<System.IO.Stream> _questionWriter;
        private readonly IRRWriter<System.IO.Stream> _rrWriter;
        private readonly ICompressionInitializer _compression;


        public MessageWriter(IHeaderWriter<System.IO.Stream> headerWriter,
            IQuestionWriter<System.IO.Stream> questionWriter,
            IRRWriter<System.IO.Stream> rrWriter,
            ICompressionInitializer compression) {

            _headerWriter = headerWriter;
            _questionWriter = questionWriter;
            _rrWriter = rrWriter;
            _compression = compression;

        }

        public void Write(System.IO.Stream destination, IMessage message) {
            Write(destination, message, true);
        }

        public void Write(System.IO.Stream destination, IMessage message, bool useCompression) {
            var cc = new CompressionContext {
                Enabled = useCompression
            };
            InternalWrite(destination, message, cc);

        }

        private void InternalWrite(System.IO.Stream destination, IMessage message, CompressionContext cc) {

            _compression.Init(cc, message);

            IHeader h = message.Header;
            List<IQuestion> qs = message.Questions;
            List<IRR> an = message.Answers;
            List<IRR> ad = message.Additionals;
            List<IRR> au = message.Authorities;

            _headerWriter.Write(destination, h);
            qs.ForEach(question => _questionWriter.Write(destination, question, cc));
            an.ForEach(answer => _rrWriter.Write(destination, answer, cc));
            ad.ForEach(additional => _rrWriter.Write(destination, additional, cc));
            au.ForEach(authority => _rrWriter.Write(destination, authority, cc));

        }
    }
}
